<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1> 1 - 手写柯里化</h1>
    <script>
        /* 柯里化 - 把接收多个参数的函数转换成一个接收单个参数, 并返回接收余下参数返回结果的一中应用 */
        /* 判断传的参数是否达到fn执行参数个数 */

        /*  -- eg1. 确定参数个数
            function sum(a, b) { }
            sum(1, 2)  //3
            const sum2 =** curry ** (sum);
            sum2(1, 2) //3
            sum2(1)(2) //3
            问curry函数怎么写能实现上述结果？
        */
        {
            let curry = function (fn, ...args) {
                // 如果参数不等, 接着增加参数
                if (fn.length > args.length)
                    return (...arguments) => curry(fn, ...args, ...arguments);
                else
                    // 参数相等, 返回柯里化后的函数
                    return fn(...args);
            }
            let sum = function (a, b) {
                return a + b;
            }
            console.log(sum(1, 2));  //3
            const sum2 = curry(sum);
            console.log(sum2(1, 2)); // 3
            console.log(sum2(1)(2)); // 3
        }

        /*  -- eg2.
            实现下面的代码
            sum(1,2)(2)() // 5
            sum(3)(3)()  // 6
        */
        {
            let sum = function (...args1) {
                let x = args1.reduce((prev, next) => (prev + next));
                return function (...args2) {
                    if (args2.length == 0) return x;
                    let y = args2.reduce((prev, next) => (prev + next));
                    return sum(x + y);
                }
            };
            console.log(sum(1, 2)(2)()); // 5
            console.log(sum(3)(3)());  // 6
        }

        /*  -- eg3.
            实现下面的代码
            add(1, 2, 3).sumof()     //6
            add(1)(2)(3).sumof()  //6
            add(1, 2)(3).sumof()   //6
        */
        {
            const add = (...args) => {
                const addFn = (args) => {
                    return args.reduce((p, c) => p + c, 0);
                };
                const fn = function (...addition) {
                    let concatArgs = args.concat(addition);
                    return add(...concatArgs);
                }
                fn.sumOf = function () {
                    console.log(addFn(args));
                }
                return fn;
            }
            add(1, 2)(3).sumOf();
        }
    </script>
</body>

</html>